local M = {
  "mason-org/mason.nvim",
  -- event = "VeryLazy",
  dependencies = {
    "mason-org/mason-lspconfig.nvim",
    -- "neovim/nvim-lspconfig", --  该插件在 neovim 0.11 以后不推荐了, 使用 vim.lsp.config 来配置
    "WhoIsSethDaniel/mason-tool-installer.nvim",

    "hrsh7th/nvim-cmp", -- 补全引擎
    "hrsh7th/cmp-nvim-lsp", -- LSP 补全源

    "j-hui/fidget.nvim", -- 插件加载工作进度

    -- jsonls 的格式服务工具
    "b0o/schemastore.nvim",
  },
}

M.config = function()
  -- fidget 必须在 lsp 配置服务之前设置
  require("fidget").setup({
    notification = {
      window = {
        -- Explicitly avoid nvim-tree's window
        avoid = {
          filetypes = { "NvimTree" }, -- Critical for continued compatibility
          buftypes = { "terminal" }, -- Optional additional exclusions
          bufnames = {}, -- Optional buffer name exclusions
        },
      },
    },
  })

  -- 单独配置工具自动安装
  local ensure_installed = {
    "stylua", -- lua formatter
    "luacheck", -- lua lint
    "selene", -- lua lint
    "biome", -- 速度比 prettier 快的格式化工具
    "prettier", -- prettier formatter
    "prettierd", -- js
    "eslint_d", -- js linter

    "isort", -- python formatter
    "black", -- python formatter
    "pylint", -- python linter
    "mypy", -- python
    "ruff", -- python
    -- "pyright",

    "codespell", -- 代码单词拼写诊断

    "golangci-lint", -- Go 综合代码检查工具
    "staticcheck", -- 高性能静态分析工具

    "codelldb",
    "clang-format", -- c/c++
    "gofumpt", -- go
    "goimports", -- go
    "jq", -- json
    "shfmt", -- sh

    -- rustup component add rustfmt
    -- "rustfmt", -- deprecated: rustfmt should now be installed via rustup

    "markdownlint", -- markdown
    -- "actionlint", -- yaml
  }

  -- local mason_tool_installer = require("mason-tool-installer")
  -- mason_tool_installer.setup({
  --   ensure_installed = ensure_installed,
  -- })

  local mason = require("mason")
  local mason_lspconfig = require("mason-lspconfig")

  mason.setup({
    ensure_installed = ensure_installed,
    install_root_dir = vim.fn.stdpath("data") .. "/mason",
    registries = {
      "github:mason-org/mason-registry",
    },

    ui = {
      border = "rounded",
      icons = {
        package_installed = "✅",
        package_pending = "⏳",
        package_uninstalled = "❌",
      },
    },
  })

  -- 管理LSP服务器
  mason_lspconfig.setup({
    -- 自动安装缺失的 LSP
    automatic_installation = true,
    -- servers for mason to install
    ensure_installed = {
      "lua_ls",
      "rust_analyzer",
      "gopls", -- Go LSP 服务器（依赖项）
      "denols",
      "ts_ls",
      "jsonls",

      "html",
      "cssls",
      "emmet_ls",
      "emmet_language_server",
      "angularls",
      "svelte",
      "tailwindcss",

      "eslint", -- lsp
    },
  })

  -- -- 通用能力配置
  -- local capabilities = vim.lsp.protocol.make_client_capabilities()

  -- ==========================================================
  -- 内置补全配置
  -- 启用 LSP 代码补全能力
  local capabilities = vim.lsp.protocol.make_client_capabilities()
  capabilities = vim.tbl_deep_extend(
    "force",
    capabilities,
    require("cmp_nvim_lsp").default_capabilities()
  )
  -- 配置 omnifunc 和 completeopt
  vim.opt.completeopt = { "menu", "menuone", "noselect", "noinsert" }
  vim.opt.shortmess:append("c")

  -- 设置 omnifunc 为 LSP
  vim.api.nvim_create_autocmd("LspAttach", {
    callback = function(args)
      local bufnr = args.buf

      local client = vim.lsp.get_client_by_id(args.data.client_id)

      if client.supports_method("textDocument/completion") then
        vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc"
      end
    end,
  })
  -- ==========================================================

  -- 通用的 LSP 配置函数
  local function setup_lsp(lsp_name, config)
    vim.lsp.config(lsp_name, config)
  end

  -- 通用获取路径
  local function get_path(names)
    return vim.fs.dirname(vim.fs.find(names, { upward = true })[1])
  end

  local toggle_inlay_hint = function(client, buf)
    if vim.lsp.inlay_hint and client.server_capabilities.inlayHintProvider then
      vim.keymap.set("n", "<Space>ht", function()
        vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled())
        vim.lsp.inlay_hint.enable(
          vim.lsp.inlay_hint.is_enabled(),
          { bufnr = buf }
        )
      end, { desc = "Toggle Inlay Hints." })
    else
      vim.notify("Not supported inlay hint")
    end
  end

  local hover_highlight_word = function(client, buf)
    -- https://neovim.io/doc/user/lsp.html
    -- vim.notify(client.name, vim.log.levels.INFO, {})

    -- 启用文档高亮
    -- -- if client.supports_method "textDocument/documentHighlight" then
    if client.server_capabilities.documentHighlightProvider then
      -- 光标所在的字符词语高亮相同的单词， 可以用插件： "RRethy/vim-illuminate",
      -- vim.api.nvim_exec(
      --   [[
      --     augroup lsp_document_highlight
      --       autocmd! * <buffer>
      --       autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
      --       autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
      --     augroup END
      --   ]],
      --   false
      -- )
      vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
        buffer = buf,
        callback = vim.lsp.buf.document_highlight,
      })
      vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
        buffer = buf,
        callback = vim.lsp.buf.clear_references,
      })
    end
  end

  -- 通用的 on_attach 函数
  local common_on_attach = function(client, bufnr)
    hover_highlight_word(client, bufnr)
    toggle_inlay_hint(client, bufnr)

    -- 通用按键映射
    local opts = { buffer = bufnr, silent = true }
    vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
    vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts)
    vim.keymap.set("n", "gr", vim.lsp.buf.references, opts)
    vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts)
    vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
    vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, opts)
    vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)
    vim.keymap.set("n", "<leader>d", vim.lsp.buf.type_definition, opts)
    vim.keymap.set("n", "<leader>fl", function()
      vim.lsp.buf.format({ async = true })
    end, opts)
  end

  -- LuaLS 配置
  setup_lsp("lua_ls", {
    capabilities = capabilities,
    on_attach = common_on_attach,
    root_dir = get_path({
      ".luarc.json",
      ".luarc.jsonc",
      ".luacheckrc",
      ".stylua.toml",
      "stylua.toml",
      "selene.toml",
      "selene.yml",
      ".git",
    }),
    cmd = { "lua-language-server" },
    filetypes = { "lua" },
    -- settings. See `:help lsp-quickstart`
    settings = {
      Lua = {
        -- 特定的补全增强
        -- completion = {
        --   callSnippet = "Replace",
        --   showWord = "Disable",
        --   keywordSnippet = "Both",
        -- },
        diagnostics = {
          globals = { "vim", "require" },
        },
        format = {
          enable = true,
          defaultConfig = {
            indent_size = "2",
            indent_style = "space",
          },
        },
        hint = {
          enable = true,
          setType = false,
          paramType = true,
          paramName = "Disable",
          semicolon = "Disable",
          arrayIndex = "Disable",
        },

        workspace = {
          library = { vim.env.VIMRUNTIME },
          checkThirdParty = false,
        },
      },
    },
  })

  -- Rust Analyzer 配置
  setup_lsp("rust_analyzer", {
    -- https://www.andersevenrud.net/neovim.github.io/lsp/configurations/rust_analyzer/
    cmd = { "rust-analyzer" },
    filetypes = { "rust" },
    root_dir = get_path({ "Cargo.toml", "rust-project.json" }),
    capabilities = capabilities,
    on_attach = common_on_attach,
    settings = {
      ["rust-analyzer"] = {
        completion = {
          autoimport = { enable = true },
          postfix = { enable = true },
        },
        diagnostic = { enable = true },
        checkOnSave = {
          command = "check", -- clippy / check
        },
        imports = {
          granularity = {
            group = "module",
          },
          prefix = "self",
        },
        cargo = {
          allFeatures = true,
          buildScripts = {
            enable = true,
          },
        },
        procMacro = {
          enable = true,
          ignored = {
            leptos_macro = {
              -- optional: --
              -- "component",
              "server",
            },
          },
        },
        inlayHints = {
          enable = true,
        },
      },
    },
  })

  -- Golang 配置
  setup_lsp("gopls", {
    cmd = { "gopls" },
    filetypes = { "go", "gomod", "gowork", "gotmpl" },
    root_dir = get_path({ "go.mod", ".git" }),
    settings = {
      gopls = {
        analyses = {
          unusedparams = true,
        },
        staticcheck = true,
      },
    },
    on_attach = common_on_attach,
    capabilities = capabilities,
  })

  -- Python 配置
  setup_lsp("pyright", {
    cmd = { "pyright-langserver", "--stdio" },
    filetypes = { "python" },
    root_dir = get_path({
      "pyproject.toml",
      "setup.py",
      "requirements.txt",
      "Pipfile",
      "pyrightconfig.json",
      ".git",
    }),
    settings = {
      python = {
        analysis = {
          autoSearchPaths = true,
          diagnosticMode = "workspace",
          useLibraryCodeForTypes = true,
          typeCheckingMode = "basic",
        },
      },
    },
    on_attach = common_on_attach,
    capabilities = capabilities,
  })

  -- TypeScript/JavaScript 配置
  setup_lsp("ts_ls", {
    cmd = { "typescript-language-server", "--stdio" },
    filetypes = {
      "javascript",
      "javascriptreact",
      "javascript.jsx",
      "typescript",
      "typescriptreact",
      "typescript.tsx",
    },
    root_dir = get_path({
      "package.json",
      "tsconfig.json",
      "jsconfig.json",
      ".git",
    }),
    init_options = {
      preferences = {
        disableSuggestions = true,
      },
      plugins = {
        {
          -- npm install -g volar @vue/typescript-plugin
          name = "@vue/typescript-plugin",
          -- location = "/usr/local/lib/node_modules/@vue/typescript-plugin",
          location = "/home/timly/installsoft/node_global/lib/node_modules/@vue/typescript-plugin",
          languages = { "javascript", "typescript", "vue" },
        },
      },
    },
    on_attach = common_on_attach,
    capabilities = capabilities,
  })

  setup_lsp("biome", {
    cmd = { "biome", "lsp-proxy" }, -- 启动命令，使用 LSP 代理模式
    filetypes = {
      "javascript",
      "typescript",
      "javascriptreact",
      "typescriptreact",
    }, -- 支持的文件类型
    -- 从项目根目录查找配置文件，确定工作区边界
    root_dir = get_path({ "biome.json", "biome.jsonc" }),
    capabilities = capabilities,
    on_attach = common_on_attach,
    single_file_support = false, -- 禁用单文件模式（避免干扰非项目文件）
    settings = {
      biome = {
        format = {
          indentStyle = "space", -- 使用空格缩进
          lineWidth = 100, -- 行宽限制
        },
        lint = {
          enabled = true,
          rules = {
            recommended = true,
            javascript = {
              noUnusedVariables = "error", -- 未使用变量报错
              noConsole = "warn", -- console 语句警告
            },
          },
        },
      },
    },
  })

  -- JSON 配置
  setup_lsp("jsonls", {
    cmd = { "vscode-json-language-server", "--stdio" },
    filetypes = { "json", "jsonc" },
    root_dir = get_path({ ".git", "package.json" }),
    settings = {
      json = {
        schemas = require("schemastore").json.schemas(),
        validate = { enable = true },
      },
    },
    on_attach = common_on_attach,
    capabilities = capabilities,
  })

  -- Emment html
  --[[
  div.container>ul>li*3→ 生成包含3个列表项的容器
  btn:primary→ 生成主要按钮
  lorem10→ 生成10个单词的虚拟文本
  ]]
  setup_lsp("emmet_ls", {
    -- 再配置代码自能补全 cmp 的 lsp
    on_attach = common_on_attach,
    capabilities = capabilities,
    cmd = { "emmet-language-server", "--stdio" },
    filetypes = {
      "html",
      "javascriptreact",
      "typescriptreact",
      "vue",
      "svelte",
      "solidjs",
      "css",
      "scss",
      "sass",
      "less",
      "stylus",
    },
    root_dir = vim.fn.getcwd(),
    single_file_support = true,
    emmet = {
      -- 包含的语言
      includeLanguages = {
        -- 为 JSX/TSX 启用 Emmet
        javascript = "javascriptreact",
        typescript = "typescriptreact",
        -- Vue 文件支持
        vue = "html",
        svelte = "html",
        -- PHP 支持
        php = "html",
        -- 其他模板语言
        ejs = "html",
        erb = "html",
        haml = "html",
      },
      showExpandedAbbreviation = "always",
    },
  })

  -- HTML LSP 配置
  -- 指定特定的文件中, 绑定快捷键（仅在 HTML 文件中生效）
  -- vim.api.nvim_create_autocmd("FileType", {
  --   pattern = "html",
  --   callback = function()
  --     local opts = { buffer = true }
  --     vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) -- 悬停查看文档
  --     vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) -- 跳转定义
  --     vim.keymap.set("n", "<leader>f", vim.lsp.buf.format, opts) -- 手动格式化
  --   end,
  -- })
  setup_lsp("html", {
    on_attach = common_on_attach,
    capabilities = capabilities,
    cmd = { "vscode-html-language-server", "--stdio" },
    filetypes = { "html", "htmldjango", "hbs", "handlebars", "vue", "php" },
    settings = {
      html = {
        hover = {
          documentation = true, -- 悬停时显示文档
          references = true,
        },
        format = {
          enable = true,
          -- 换行配置
          wrapLineLength = 0, -- 行宽限制, 0 表示不换行
          wrapAttributes = "auto", -- 自动换行属性
          -- 缩进配置
          indentInnerHtml = true,
          indentHandlebars = false,
          -- 空行配置
          preserveNewLines = true,
          maxPreserveNewLines = 1,
          -- 额外空行标签
          extraLiners = "head, body, html, script, style",
          -- 不格式化的内容
          unformatted = "wbr",
          contentUnformatted = "pre,code,textarea",
          -- 其他配置
          endWithNewline = true,
          keepBlanks = true,
        },
      },
    },
  })

  --[[
  setup_lsp("cssls", {
    on_attach = common_on_attach,
    capabilities = capabilities,
    filetypes = { "css", "scss", "less", "stylus" }, -- 支持的文件类型
    settings = {
      css = {
        validate = true,
        completion = { completePropertyWithSemicolon = true }, -- 补全后自动添加分号
        lint = {
          unknownAtRules = "ignore", -- 忽略未知的 @ 规则（如 Tailwind 的 @apply）
        },
      },
      scss = { validate = true },
      less = { validate = true },
      stylus = { validate = true },
      -- 自定义 CSS 处理器（如 PostCSS）的支持
      cssls = {
        experimental = { enableProjectDiagnostics = true }, -- 项目级诊断（实验性）
      },
    },
  })

  setup_lsp("tailwindcss", {
    on_attach = common_on_attach,
    capabilities = capabilities,
    filetypes = {
      "css",
      "scss",
      "less",
      "html",
      "javascriptreact",
      "typescriptreact",
    },
  })
  ]]

  -- setup_lsp("svelte", {})
  -- setup_lsp("denols", {})
  -- setup_lsp("unocss", {})
  -- setup_lsp("volar", {})
end

return M
